package xyz.lne.researchgroupmanage.controller;


import lombok.RequiredArgsConstructor;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import org.springframework.web.multipart.MultipartFile;
import xyz.lne.researchgroupmanage.annotation.AnonymousGetMapping;
import xyz.lne.researchgroupmanage.annotation.AnonymousPostMapping;
import xyz.lne.researchgroupmanage.annotation.IgnoreResponseAdvice;
import xyz.lne.researchgroupmanage.controller.request.DirectoryRequest;
import xyz.lne.researchgroupmanage.controller.request.FileRequest;
import xyz.lne.researchgroupmanage.controller.request.ImageRequest;
import xyz.lne.researchgroupmanage.controller.response.FileResponse;
import xyz.lne.researchgroupmanage.security.UserPower;
import xyz.lne.researchgroupmanage.service.FileService;
import xyz.lne.researchgroupmanage.service.dataTransferObject.FileDTO;
import xyz.lne.researchgroupmanage.util.SecurityUtils;
import xyz.lne.researchgroupmanage.util.enums.FileKind;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author team7
 * @since 2021-01-19
 */
@RestController
@RequiredArgsConstructor
@RequestMapping("/file")
public class FileController {

    private final FileService fileService;

    // 上传文件至云盘
    @PostMapping("/upload-disk")
    public FileResponse uploadFile(@RequestParam Integer parentId, @RequestParam Integer researchId, @RequestParam MultipartFile uploadFile){
//    public Integer uploadFile(FileRequest fileRequest){
        Integer userId = UserPower.check(UserPower.RESEARCH_JOIN, researchId);
        FileDTO fileDTO = fileService.uploadFileShare(uploadFile, parentId, researchId, userId);
//        FileDTO fileDTO = fileService.uploadFileShare(fileRequest.getUploadFile(), fileRequest.getParentId(), fileRequest.getResearchId(), 0);
        return FileResponse.convertFromFileDTO(fileDTO);
    }

    @AnonymousPostMapping("/upload-task")
    public FileResponse uploadTask(@RequestParam Integer researchId, @RequestParam MultipartFile uploadFile){
        //Integer userId = UserPower.check(UserPower.RESEARCH_JOIN, researchId);
        Integer userId=SecurityUtils.getCurrentUserId();
        researchId=0;
        FileDTO fileDTO = fileService.uploadFileTaskOrDocument(uploadFile, FileKind.TASK_FILE.getKind(),
                researchId, userId);

        return FileResponse.convertFromFileDTO(fileDTO);
    }

    @PostMapping("/upload-document")
    public FileResponse uploadDocument(@RequestParam Integer researchId, @RequestParam MultipartFile uploadFile){
        Integer userId = UserPower.check(UserPower.RESEARCH_JOIN, researchId);
        FileDTO fileDTO = fileService.uploadFileTaskOrDocument(uploadFile, FileKind.DOCUMENT_FILE.getKind(),
                researchId, userId);
        return FileResponse.convertFromFileDTO(fileDTO);
    }

    //   上传图片
    @AnonymousPostMapping("/upload-image")
    public Integer uploadImage(@RequestParam Integer kind, @RequestParam MultipartFile image
    ){
        return fileService.uploadImage(image, kind).getFileId();
    }

    @PostMapping("/make-directory")
    public FileResponse makeDirectory(@RequestBody DirectoryRequest directoryRequest){
        Integer userId = UserPower.check(UserPower.RESEARCH_JOIN, directoryRequest.getResearchId());
        FileDTO fileDTO = fileService.makeDirectory(directoryRequest.getDirectoryName(), directoryRequest.getResearchId(), directoryRequest.getParentId(), userId);
        return FileResponse.convertFromFileDTO(fileDTO);
    }

    @PostMapping("/rename-directory")
    public FileResponse renameDirectory(@RequestBody DirectoryRequest directoryRequest){
        Integer userId = UserPower.check(UserPower.RESEARCH_JOIN, directoryRequest.getResearchId());
        FileDTO fileDTO = fileService.renameDirectory(directoryRequest.getFileId(), directoryRequest.getDirectoryName(), userId);
        return FileResponse.convertFromFileDTO(fileDTO);
    }

    //    逻辑删除
    @GetMapping("/delete")
    public Boolean deleteFile(@RequestParam Integer fileId){
        return fileService.deleteFile(fileId);
    }

    //    课题组原始层目录的文件
    @GetMapping("/list-research")
    public List<FileResponse> findFileListByResearchId(@RequestParam Integer researchId){
        List<FileDTO> fileDTOList = fileService.findResearchFileList(researchId);
        return fileDTOList.stream().map(FileResponse::convertFromFileDTO).collect(Collectors.toList());
    }

    //    文件夹下的子文件
    @GetMapping("/list-directory")
    public List<FileResponse> findChildrenFileList(@RequestParam Integer parentId){
        List<FileDTO> fileDTOList = fileService.findChildrenFileList(parentId);
        return fileDTOList.stream().map(FileResponse::convertFromFileDTO).collect(Collectors.toList());
    }

//    获取单个文件的信息 如文档和任务附带的
    @IgnoreResponseAdvice
    @RequestMapping("/download-small")
    public ResponseEntity<InputStreamResource> downloadSmallFile(@RequestParam Integer fileId) throws IOException {
        FileDTO fileDTO = fileService.findFileByFileId(fileId);
        String path = fileDTO.getPath();;
        File file = new File(path);
        if (!file.exists()) path ="C:\\research_group_manage\\user_icon\\default.jpeg";
        FileSystemResource fileSystemResource = new FileSystemResource(path);
        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", fileSystemResource.getFilename()));
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");
        return ResponseEntity
                .ok()
                .headers(headers)
                .contentLength(fileSystemResource.contentLength())
                .contentType(MediaType.parseMediaType("application/octet-stream"))
                .body(new InputStreamResource(fileSystemResource.getInputStream()));
    }

//    下载云盘上的文件
    @IgnoreResponseAdvice
    @RequestMapping("/download-big")
    public void downloadBigFile(@RequestParam Integer fileId, HttpServletRequest request, HttpServletResponse response) throws IOException {
        FileDTO fileDTO = fileService.findFileByFileId(fileId);
        String path = fileDTO.getPath();
        File downloadFile = new File(path);
        ServletContext context = request.getServletContext();
        // get MIME type of the file
        String mimeType = context.getMimeType(path);
        if (mimeType == null) {
            // set to binary type if MIME mapping not found
            mimeType = "application/octet-stream";
        }
        // set content attributes for the response
        response.setContentType(mimeType);
        response.setContentLength((int) downloadFile.length());
        // set headers for the response
        String headerKey = "Content-Disposition";
        String headerValue = String.format("attachment; filename=\"%s\"",
                downloadFile.getName());
        response.setHeader(headerKey, headerValue);
        // Copy the stream to the response's output stream.
        InputStream myStream = new FileInputStream(path);
        IOUtils.copy(myStream, response.getOutputStream());
        response.flushBuffer();
    }

    @IgnoreResponseAdvice
    @RequestMapping("/download-back")
    public String downloadFileBack(@RequestParam Integer fileId, HttpServletRequest request, HttpServletResponse response){
        FileDTO fileDTO = fileService.findFileByFileId(fileId);
        String path = fileDTO.getPath();
        File file = new File(path);
        if (file.exists()) {
            response.setContentType("application/octet-stream");//
            response.setHeader("content-type", "application/octet-stream");
            response.setHeader("Content-Disposition", "attachment;fileName=" + fileDTO.getFileName());// 设置文件名
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
                System.out.println("success");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return null;
    }
}

